package com.atguigu.schedule.service.impl;

import com.atguigu.schedule.pojo.FaceDetectionResult;
import com.atguigu.schedule.pojo.FaceDetectionRecord;
import com.atguigu.schedule.pojo.PersonTrackingResult;
import com.atguigu.schedule.service.FaceTrackingService;
import com.atguigu.schedule.service.FaceDetectionRecordService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;

import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.Base64;

/**
 * 简化版人脸识别和行人跟踪服务实现
 * 使用Python脚本进行实际的人脸识别处理
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class SimpleFaceTrackingServiceImpl implements FaceTrackingService {
    
    private final FaceDetectionRecordService faceDetectionRecordService;
    
    private Map<String, Integer> faceLabels;
    private Map<Integer, String> labelToName;
    private int nextLabelId;
    private String datasetPath;
    private String pythonScriptPath;
    
    // 行人跟踪相关
    private Map<Integer, PersonTrackingResult> trackedPersons;
    private int nextTrackId;
    
    // 线程池和超时配置
    private ExecutorService executorService;
    private static final int PROCESS_TIMEOUT_SECONDS = 30;
    
    @PostConstruct
    public void init() {
        try {
            // 初始化人脸识别
            faceLabels = new ConcurrentHashMap<>();
            labelToName = new ConcurrentHashMap<>();
            nextLabelId = 0;
            
            // 初始化行人跟踪
            trackedPersons = new ConcurrentHashMap<>();
            nextTrackId = 0;
            
            // 初始化线程池
            executorService = Executors.newFixedThreadPool(4);
            
            // 设置路径
            datasetPath = "/opt/smart-care-car/dataset";
            pythonScriptPath = "/opt/smart-care-car/simple_face_detect.py";
            
            // 创建数据集目录
            Files.createDirectories(Paths.get(datasetPath));
            
            // 加载现有的人脸数据
            loadExistingFaces();
            
            log.info("简化版人脸识别和行人跟踪服务初始化完成");
            
        } catch (Exception e) {
            log.error("人脸识别服务初始化失败", e);
            // 即使初始化失败，也继续运行，避免影响整个应用
        }
    }
    
    @Override
    public List<FaceDetectionResult> detectFaces(byte[] imageData) {
        List<FaceDetectionResult> results = new ArrayList<>();
        String tempImagePath = null;
        
        try {
            // 创建临时图像文件
            tempImagePath = "/tmp/temp_detect_" + System.currentTimeMillis() + ".jpg";
            Files.write(Paths.get(tempImagePath), imageData);
            log.info("创建临时图像文件: {}", tempImagePath);
            
            // 异步调用Python脚本进行人脸检测和识别
            CompletableFuture<ProcessResult> future = executePythonScript("detect", tempImagePath);
            
            try {
                ProcessResult result = future.get(PROCESS_TIMEOUT_SECONDS, TimeUnit.SECONDS);
                
                if (result.isSuccess()) {
                    // 解析输出结果
                    log.info("Python脚本执行成功，退出码: {}", result.getExitCode());
                    log.info("Python脚本输出: '{}'", result.getOutput());
                    String[] lines = result.getOutput().split("\n");
                    log.info("输出行数: {}", lines.length);
                    for (String line : lines) {
                        if (line.startsWith("FACE:")) {
                            String[] parts = line.substring(5).split(",");
                            if (parts.length >= 4) {
                                int x = Integer.parseInt(parts[0]);
                                int y = Integer.parseInt(parts[1]);
                                int width = Integer.parseInt(parts[2]);
                                int height = Integer.parseInt(parts[3]);
                                
                                FaceDetectionResult faceResult = new FaceDetectionResult(x, y, width, height);
                                
                                // 如果有识别结果
                                if (parts.length >= 6) {
                                    String name = parts[4];
                                    double confidence = Double.parseDouble(parts[5]);
                                    faceResult.setRecognizedName(name);
                                    faceResult.setConfidence(confidence);
                                    faceResult.setRecognized(!"Unknown".equals(name));
                                    
                                    // 保存检测记录到数据库
                                    if (!"Unknown".equals(name)) {
                                        try {
                                            FaceDetectionRecord record = new FaceDetectionRecord();
                                            record.setUsername(name);
                                            record.setConfidence(BigDecimal.valueOf(confidence));
                                            record.setDetectionTime(LocalDateTime.now());
                                            record.setImagePath(tempImagePath);
                                            record.setVideoSource("webrtc://8.136.52.147:8080/live/livestream");
                                            record.setSessionId("9999");
                                            record.setFaceX(x);
                                            record.setFaceY(y);
                                            record.setFaceWidth(width);
                                            record.setFaceHeight(height);
                                            
                                            faceDetectionRecordService.saveDetectionRecord(record);
                                            log.info("保存人脸检测记录: 用户={}, 置信度={}", name, confidence);
                                        } catch (Exception e) {
                                            log.error("保存人脸检测记录失败", e);
                                        }
                                    }
                                }
                                
                                results.add(faceResult);
                            }
                        } else if (line.startsWith("ERROR:") || line.contains("错误")) {
                            log.warn("Python脚本错误: {}", line);
                        }
                    }
                } else {
                    log.error("Python脚本执行失败，退出码: {}, 输出: {}", result.getExitCode(), result.getOutput());
                }
                
            } catch (Exception e) {
                log.error("等待Python脚本执行结果失败", e);
            } finally {
                // 清理临时文件
                if (tempImagePath != null) {
                    try {
                        Files.deleteIfExists(Paths.get(tempImagePath));
                    } catch (IOException e) {
                        log.warn("删除临时文件失败: {}", tempImagePath, e);
                    }
                }
            }
            
        } catch (Exception e) {
            log.error("人脸检测失败", e);
        }
        
        return results;
    }
    
    @Override
    public List<PersonTrackingResult> detectPersons(byte[] imageData) {
        List<PersonTrackingResult> results = new ArrayList<>();
        
        try {
            // 保存临时图像文件
            String tempImagePath = "/tmp/temp_person_" + System.currentTimeMillis() + ".jpg";
            Files.write(Paths.get(tempImagePath), imageData);
            
            // 异步调用Python脚本进行行人检测
            CompletableFuture<ProcessResult> future = executePythonScript("detect_persons", tempImagePath);
            
            try {
                ProcessResult result = future.get(PROCESS_TIMEOUT_SECONDS, TimeUnit.SECONDS);
                
                if (result.isSuccess()) {
                    // 解析输出结果
                    String[] lines = result.getOutput().split("\n");
                    for (String line : lines) {
                        if (line.startsWith("PERSON:")) {
                            String[] parts = line.substring(7).split(",");
                            if (parts.length >= 4) {
                                int x = Integer.parseInt(parts[0]);
                                int y = Integer.parseInt(parts[1]);
                                int width = Integer.parseInt(parts[2]);
                                int height = Integer.parseInt(parts[3]);
                                
                                PersonTrackingResult personResult = new PersonTrackingResult(x, y, width, height, nextTrackId++);
                                
                                // 简单的跟踪逻辑：检查是否与现有跟踪对象重叠
                                boolean isNewPerson = true;
                                for (PersonTrackingResult existing : trackedPersons.values()) {
                                    if (isOverlapping(personResult, existing)) {
                                        personResult.setTrackId(existing.getTrackId());
                                        personResult.setNewPerson(false);
                                        isNewPerson = false;
                                        break;
                                    }
                                }
                                
                                if (isNewPerson) {
                                    trackedPersons.put(personResult.getTrackId(), personResult);
                                }
                                
                                results.add(personResult);
                            }
                        } else if (line.startsWith("ERROR:") || line.contains("错误")) {
                            log.warn("Python脚本错误: {}", line);
                        }
                    }
                } else {
                    log.error("Python脚本执行失败，退出码: {}, 输出: {}", result.getExitCode(), result.getOutput());
                }
                
            } catch (Exception e) {
                log.error("等待Python脚本执行结果失败", e);
            } finally {
                // 清理临时文件
                // 不再需要清理临时文件，因为我们使用base64直接传递数据
            }
            
        } catch (Exception e) {
            log.error("行人检测失败", e);
        }
        
        return results;
    }
    
    @Override
    public String recognizeFace(byte[] faceImageData) {
        try {
            // 保存临时图像文件
            String tempImagePath = "/tmp/temp_recognize_" + System.currentTimeMillis() + ".jpg";
            Files.write(Paths.get(tempImagePath), faceImageData);
            
            // 异步调用Python脚本进行人脸识别
            CompletableFuture<ProcessResult> future = executePythonScript("recognize_face", tempImagePath);
            
            try {
                ProcessResult result = future.get(PROCESS_TIMEOUT_SECONDS, TimeUnit.SECONDS);
                
                if (result.isSuccess()) {
                    // 解析输出结果
                    String[] lines = result.getOutput().split("\n");
                    for (String line : lines) {
                        if (!line.startsWith("ERROR:") && !line.contains("错误") && !line.trim().isEmpty()) {
                            // 清理临时文件
                            // 不再需要清理临时文件，因为我们使用base64直接传递数据
                            return line.trim();
                        } else if (line.startsWith("ERROR:") || line.contains("错误")) {
                            log.warn("Python脚本错误: {}", line);
                        }
                    }
                } else {
                    log.error("Python脚本执行失败，退出码: {}, 输出: {}", result.getExitCode(), result.getOutput());
                }
                
            } catch (Exception e) {
                log.error("等待Python脚本执行结果失败", e);
            } finally {
                // 清理临时文件
                // 不再需要清理临时文件，因为我们使用base64直接传递数据
            }
            
            return "Unknown";
            
        } catch (Exception e) {
            log.error("人脸识别失败", e);
            return "Unknown";
        }
    }
    
    @Override
    public boolean addFaceSample(String name, byte[] imageData) {
        String tempImagePath = null;
        try {
            // 创建临时图像文件
            tempImagePath = "/tmp/temp_add_" + System.currentTimeMillis() + ".jpg";
            Files.write(Paths.get(tempImagePath), imageData);
            
            // 异步调用Python脚本添加人脸样本
            CompletableFuture<ProcessResult> future = executePythonScript("add", name, tempImagePath);
            
            try {
                ProcessResult result = future.get(PROCESS_TIMEOUT_SECONDS, TimeUnit.SECONDS);
                
                if (result.isSuccess()) {
                    // 解析输出结果
                    String[] lines = result.getOutput().split("\n");
                    boolean success = false;
                    for (String line : lines) {
                        if (line.startsWith("SUCCESS")) {
                            success = true;
                            break;
                        } else if (line.startsWith("ERROR:")) {
                            log.warn("Python脚本错误: {}", line);
                        }
                    }
                    
                    if (success) {
                        // 更新标签映射
                        if (!faceLabels.containsKey(name)) {
                            faceLabels.put(name, nextLabelId);
                            labelToName.put(nextLabelId, name);
                            nextLabelId++;
                        }
                        
                        log.info("成功添加人脸样本: {}", name);
                        return true;
                    } else {
                        log.error("添加人脸样本失败: {}", result.getOutput());
                        return false;
                    }
                } else {
                    log.error("Python脚本执行失败，退出码: {}, 输出: {}", result.getExitCode(), result.getOutput());
                    return false;
                }
                
            } catch (Exception e) {
                log.error("等待Python脚本执行结果失败", e);
                return false;
            } finally {
                // 清理临时文件
                if (tempImagePath != null) {
                    try {
                        Files.deleteIfExists(Paths.get(tempImagePath));
                    } catch (IOException e) {
                        log.warn("删除临时文件失败: {}", tempImagePath, e);
                    }
                }
            }
            
        } catch (Exception e) {
            log.error("添加人脸样本失败", e);
            return false;
        }
    }
    
    @Override
    public boolean trainFaceModel() {
        try {
            // 检查模型文件是否存在
            Path modelPath = Paths.get("/opt/smart-care-car/trainer.yml");
            if (Files.exists(modelPath)) {
                log.info("人脸识别模型已存在，跳过训练");
                return true;
            }
            
            // 异步调用Python脚本训练模型
            CompletableFuture<ProcessResult> future = executePythonScript("train");
            
            try {
                ProcessResult result = future.get(PROCESS_TIMEOUT_SECONDS, TimeUnit.SECONDS);
                
                if (result.isSuccess()) {
                    // 解析输出信息
                    String[] lines = result.getOutput().split("\n");
                    for (String line : lines) {
                        if (line.contains("模型训练完成") || line.contains("训练完成")) {
                            log.info("Python脚本输出: {}", line);
                        } else if (line.startsWith("ERROR:") || line.contains("错误")) {
                            log.warn("Python脚本错误: {}", line);
                        }
                    }
                    
                    log.info("人脸识别模型训练完成");
                    return true;
                } else {
                    log.error("Python脚本执行失败，退出码: {}, 输出: {}", result.getExitCode(), result.getOutput());
                    return false;
                }
                
            } catch (Exception e) {
                log.error("等待Python脚本执行结果失败", e);
                // 如果模型文件存在，仍然返回成功
                if (Files.exists(modelPath)) {
                    log.info("模型文件存在，返回训练成功");
                    return true;
                }
                return false;
            }
            
        } catch (Exception e) {
            log.error("训练人脸识别模型失败", e);
            // 如果模型文件存在，仍然返回成功
            Path modelPath = Paths.get("/opt/smart-care-car/trainer.yml");
            if (Files.exists(modelPath)) {
                log.info("模型文件存在，返回训练成功");
                return true;
            }
            return false;
        }
    }
    
    @Override
    public List<String> getRegisteredFaces() {
        try {
            // 调用Python脚本获取已注册人脸列表
            CompletableFuture<ProcessResult> future = executePythonScript("list");
            ProcessResult result = future.get(5, TimeUnit.SECONDS);
            
            if (result.isSuccess()) {
                // 解析JSON输出
                String output = result.getOutput().trim();
                if (output.startsWith("[") && output.endsWith("]")) {
                    // 简单的JSON解析
                    output = output.substring(1, output.length() - 1);
                    if (output.isEmpty()) {
                        return new ArrayList<>();
                    }
                    String[] names = output.split(",");
                    List<String> faces = new ArrayList<>();
                    for (String name : names) {
                        name = name.trim().replace("\"", "");
                        if (!name.isEmpty()) {
                            faces.add(name);
                        }
                    }
                    return faces;
                }
            }
        } catch (Exception e) {
            log.error("获取已注册人脸列表失败", e);
        }
        
        // 降级到本地缓存
        return new ArrayList<>(faceLabels.keySet());
    }
    
    /**
     * 获取服务状态信息
     * @return 状态信息Map
     */
    public Map<String, Object> getStatus() {
        Map<String, Object> status = new HashMap<>();
        status.put("serviceAvailable", true);
        status.put("registeredFaceCount", faceLabels.size());
        status.put("registeredFaces", new ArrayList<>(faceLabels.keySet()));
        status.put("detectedFaces", 0); // 实时检测的人脸数量
        status.put("detectedPersons", trackedPersons.size()); // 实时检测的行人数量
        status.put("recentRecognitions", new ArrayList<>()); // 最近的识别结果
        return status;
    }
    
    @Override
    public boolean deleteFaceData(String name) {
        try {
            if (!faceLabels.containsKey(name)) {
                return false;
            }
            
            // 删除数据集目录
            Path personDir = Paths.get(datasetPath, name);
            if (Files.exists(personDir)) {
                Files.walk(personDir)
                    .sorted(Comparator.reverseOrder())
                    .forEach(path -> {
                        try {
                            Files.delete(path);
                        } catch (IOException e) {
                            log.warn("删除文件失败: {}", path, e);
                        }
                    });
            }
            
            // 从标签映射中移除
            Integer labelId = faceLabels.remove(name);
            if (labelId != null) {
                labelToName.remove(labelId);
            }
            
            // 重新训练模型
            trainFaceModel();
            
            log.info("成功删除人脸数据: {}", name);
            return true;
            
        } catch (Exception e) {
            log.error("删除人脸数据失败", e);
            return false;
        }
    }
    
    /**
     * 加载现有的人脸数据
     */
    private void loadExistingFaces() {
        try {
            if (!Files.exists(Paths.get(datasetPath))) {
                return;
            }
            
            Files.walk(Paths.get(datasetPath))
                .filter(Files::isDirectory)
                .filter(path -> !path.equals(Paths.get(datasetPath)))
                .forEach(personDir -> {
                    String personName = personDir.getFileName().toString();
                    faceLabels.put(personName, nextLabelId);
                    labelToName.put(nextLabelId, personName);
                    nextLabelId++;
                });
            
            log.info("加载了 {} 个已注册的人脸", faceLabels.size());
            
        } catch (Exception e) {
            log.error("加载现有人脸数据失败", e);
        }
    }
    
    
    /**
     * 通用的Python脚本调用方法，包含超时机制
     */
    private CompletableFuture<ProcessResult> executePythonScript(String... args) {
        return CompletableFuture.supplyAsync(() -> {
            try {
                ProcessBuilder pb = new ProcessBuilder("python3", pythonScriptPath);
                pb.command().addAll(Arrays.asList(args));
                pb.directory(new File("/opt/smart-care-car/人脸识别"));
                pb.redirectErrorStream(true);
                
                Process process = pb.start();
                
                // 读取输出
                StringBuilder output = new StringBuilder();
                try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
                    String line;
                    while ((line = reader.readLine()) != null) {
                        output.append(line).append("\n");
                    }
                }
                
                int exitCode = process.waitFor();
                return new ProcessResult(exitCode, output.toString());
                
            } catch (Exception e) {
                log.error("执行Python脚本失败", e);
                return new ProcessResult(-1, "执行失败: " + e.getMessage());
            }
        }, executorService).orTimeout(PROCESS_TIMEOUT_SECONDS, TimeUnit.SECONDS)
        .exceptionally(throwable -> {
            log.error("Python脚本执行超时或异常", throwable);
            return new ProcessResult(-1, "执行超时或异常: " + throwable.getMessage());
        });
    }
    
    /**
     * 进程执行结果
     */
    private static class ProcessResult {
        private final int exitCode;
        private final String output;
        
        public ProcessResult(int exitCode, String output) {
            this.exitCode = exitCode;
            this.output = output;
        }
        
        public int getExitCode() { return exitCode; }
        public String getOutput() { return output; }
        public boolean isSuccess() { return exitCode == 0; }
    }
    
    /**
     * 检查两个检测结果是否重叠
     */
    private boolean isOverlapping(PersonTrackingResult result1, PersonTrackingResult result2) {
        int overlapX = Math.max(0, Math.min(result1.getX() + result1.getWidth(), result2.getX() + result2.getWidth()) - 
                               Math.max(result1.getX(), result2.getX()));
        int overlapY = Math.max(0, Math.min(result1.getY() + result1.getHeight(), result2.getY() + result2.getHeight()) - 
                               Math.max(result1.getY(), result2.getY()));
        
        int area1 = result1.getWidth() * result1.getHeight();
        int area2 = result2.getWidth() * result2.getHeight();
        int overlapArea = overlapX * overlapY;
        
        double overlapRatio = (double) overlapArea / Math.min(area1, area2);
        return overlapRatio > 0.3; // 30%重叠阈值
    }
    
    /**
     * 销毁方法，关闭线程池
     */
    @PreDestroy
    public void destroy() {
        if (executorService != null && !executorService.isShutdown()) {
            log.info("正在关闭人脸识别服务线程池...");
            executorService.shutdown();
            try {
                if (!executorService.awaitTermination(5, TimeUnit.SECONDS)) {
                    log.warn("线程池未能在5秒内正常关闭，强制关闭");
                    executorService.shutdownNow();
                }
            } catch (InterruptedException e) {
                log.warn("等待线程池关闭时被中断", e);
                executorService.shutdownNow();
                Thread.currentThread().interrupt();
            }
            log.info("人脸识别服务线程池已关闭");
        }
    }
}
